#pragma once
#include <memory>
#include <mutex>
namespace Thread::util {

// 禁止拷贝工具类
class Nocopyable {
protected:
  // 允许构造和析构
  Nocopyable() = default;
  ~Nocopyable() = default;

  // 禁止拷贝构造和拷贝赋值
  Nocopyable(const Nocopyable &) = delete;
  Nocopyable &operator=(const Nocopyable &) = delete;
};

// 单例类基类

template <class __Class> class Singleton : public Nocopyable {
public:
  // 允许子类析构
  virtual ~Singleton() = default;

  template <typename... Args>
  static std::shared_ptr<__Class> GetInstance(Args &&...args) {
    std::call_once(__flag, [&]() {
      // 这里只能使用new
      //__Class声明了Singleton友元，让Singleton能访问__Class的构造函数，
      //  但是make_shared是在内部构造一个新实例，而构造这个实例的类无法访问到构造函数，所以只能使用new
      __instance =
          std::shared_ptr<__Class>(new __Class(std::forward<Args>(args)...));
    });
    return __instance;
  }

private:
  static inline std::shared_ptr<__Class> __instance{nullptr};
  static inline std::once_flag __flag;
};

} // namespace Thread::util
